/******************************************************************************
*
* This file is part of FreeTrack (http://code.google.com/p/qtfreetrack).
* BY Willy Gardiol (willy@gardiol.org)
*
* FreeTrack is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FreeTrack is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Foobar.  If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/

#include "workerprocess.h"

#include "controls/ftpushbutton.h"
#include "controls/fticonlabel.h"
#include "controls/ftmessagebox.h"
#include "controls/ftlabel.h"
#include "controls/ftvboxlayout.h"
#include "controls/fthboxlayout.h"

bool worker_already_open = false;
WorkerProcess::WorkerProcess(int nl, const QString& title) :
    RotatingDialog()
{
    nLabels = nl;
    please_terminate = still_running = error = false;

    // Set title
    wait_title = new FTLabel(title);

    // Set all progress bars...
    wait_progress = new QProgressBar();
    wait_progress->setMinimum(0);
    wait_progress->setMaximum(100);
    wait_progress->setValue(0);
    wait_progress->hide();
    progressValue = progressRange = -1;

    for (int p = 0; p < nLabels; p++ )
    {
        FTLabel* wait_progress_label = new FTLabel();
        wait_progress_label->setAlignment( Qt::AlignCenter );
        wait_progress_labels.append( wait_progress_label );
    }

    wait_icon = new FTIconLabel( QIcon( ":/icons/wait.png"), FTControls::IconBig );

    wait_cancel = new FTPushButton( tr("Abort...") );

    // Signal worker when the user select "reject"
    connect( wait_cancel, SIGNAL(clicked()), this, SLOT(pleaseTerminate()));
}

bool WorkerProcess::run()
{
    if ( worker_already_open )
        return false;

    worker_already_open = true;
    // Let execute the queue of events and show!
    qApp->processEvents( QEventLoop::AllEvents );
    showFullScreen();
    qApp->processEvents( QEventLoop::AllEvents );

    bool run_status_ok = false;

    please_terminate = error = false;
    still_running = true;
    run_status_ok  = do_stuff();
    still_running = false;
    hide();
    if ( !run_status_ok )
        FTMessageBox::Error(tr("An error has occurred!"),
                              error_string );

    worker_already_open = false;
    return run_status_ok;
}

bool WorkerProcess::do_stuff()
{
    return true;
}

bool WorkerProcess::isTerminated()
{
    return still_running;
}

void WorkerProcess::pleaseTerminate()
{
    error_string = tr("Cancelled");
    please_terminate = true;
}

QString WorkerProcess::getErrorString()
{
    return error_string;
}

void WorkerProcess::setErrorString(const QString& se )
{
    error_string = se;
    error = true;
}

void WorkerProcess::setMinMaxProgress(int max, int min)
{
    progressRange = abs( max - min );
    if ( progressRange != 0 )
        wait_progress->show();
    else
        wait_progress->hide();
    qApp->processEvents( QEventLoop::AllEvents );
}

void WorkerProcess::updateProgress(int value)
{
    static QDateTime last_update;
    if ( (progressRange > 0) && (value> 0 ) )
    {
        QDateTime now = QDateTime::currentDateTime();
        if ( last_update.isValid() &&
             last_update.secsTo( now ) < 1 )
            return;
        last_update = now;
        int new_progressValue = value * 100 / progressRange;
        // We always update, to ensure text at least is updated every 1 secs.
//        if ( (new_progressValue != progressValue) )
        {
            progressValue = new_progressValue;
            wait_progress->setValue( progressValue );
            qApp->processEvents( QEventLoop::AllEvents );
        }
    }
}

void WorkerProcess::updateText(int who, const QString & str)
{
    if ( (who > -1) &&
         (who < nLabels ) )
    {
        FTLabel* label = wait_progress_labels.at(who);
        if ( str != label->text() )
            label->setText( str );
    }
}

void WorkerProcess::updateTextProgress(int who, const QString & str, int val)
{
    updateText(who, str);
    updateProgress( val );
}

QLayout* WorkerProcess::createVertical()
{
    // Build widget layout
    FTVBoxLayout* layout = new FTVBoxLayout();

    layout->addWidget( wait_title );
    layout->addStretch();
    layout->addWidget( wait_progress );

    for ( int i = 0; i < nLabels; i++ )
        layout->addWidget( wait_progress_labels.at(i) );

    // Set the wait icon...
    FTHBoxLayout* hor = new FTHBoxLayout();
    hor->addStretch();
    hor->addWidget( wait_icon );
    hor->addStretch();

    layout->addStretch();
    layout->addLayout( hor );

    // Abort button
    layout->addStretch();
    layout->addWidget( wait_cancel );

    return layout;
}
